package com.piece.core.framework.util.file;

import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;

@Slf4j
public class PathUtil {

    /**
     * 定位相对路径所对应的绝对路径。
     *
     * @param relatedPath 相对路径
     * @param cls         用来定位的类
     * @return 相对路径所对应的绝对路径
     */
    public static final String getFullPathRelateClass(String relatedPath, Class<?> cls) {
        String path = null;
        if (null == relatedPath) {
            throw new NullPointerException();
        }
        String clsPath = getPathFromClass(cls);
        File clsFile = new File(clsPath);
        String tempPath = clsFile.getParent() + File.separator + relatedPath;
        File file = new File(tempPath);
        try {
            path = file.getCanonicalPath();
        } catch (IOException e) {
            log.error("获取文件绝对路径失败：{}", e.getMessage());
        }
        return path;
    }

    /**
     * 获取class文件所在绝对路径
     */
    public static final String getPathFromClass(Class<?> cls) {
        String path = null;
        if (null == cls) {
            throw new NullPointerException();
        }
        URL url = getClassLocationURL(cls);
        if (null != url) {
            path = url.getPath();
            if ("jar".equalsIgnoreCase(url.getProtocol())) {
                try {
                    path = new URL(path).getPath();
                } catch (MalformedURLException e) {
                }
                int location = path.indexOf("!/");
                if (location != -1) {
                    path = path.substring(0, location);
                }
            }
            File file = new File(path);
            try {
                path = file.getCanonicalPath();
            } catch (IOException e) {
                log.error("获取Class文件绝对路径失败：{}", e.getMessage());
            }
        }
        return path;
    }

    /**
     * 获取类的class文件位置的URL
     */
    private static URL getClassLocationURL(final Class<?> cls) {
        if (null == cls) {
            throw new IllegalArgumentException("null input: cls");
        }
        URL result = null;
        final String clsAsResource = cls.getName().replace('.', '/').concat(".class");
        final ProtectionDomain pd = cls.getProtectionDomain();
        if (null != pd) {
            final CodeSource cs = pd.getCodeSource();
            if (null != cs) {
                result = cs.getLocation();
            }
            if (null != result) {
                if ("file".equals(result.getProtocol())) {
                    try {
                        if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip")) {
                            result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clsAsResource));
                        } else if (new File(result.getFile()).isDirectory()) {
                            result = new URL(result, clsAsResource);
                        }
                    } catch (MalformedURLException ignore) {
                    }
                }
            }
        }
        if (null == result) {
            final ClassLoader clsLoader = cls.getClassLoader();
            result = null != clsLoader ? clsLoader.getResource(clsAsResource)
                    : ClassLoader.getSystemResource(clsAsResource);
        }
        return result;
    }
}
